﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Configuration;
using System.Web.Configuration;

namespace Landscape
{
    sealed class Globals
    {
        #region Path management

        public static string AbsPath(string path)
        {
            if (System.Web.Hosting.HostingEnvironment.IsHosted) {
                return System.Web.Hosting.HostingEnvironment.MapPath(path);
            } else {
                if (path.StartsWith("~")) path = path.Substring(1);
                if (path.StartsWith("/")) path = path.Substring(1);
                return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, path);
            }
        }

        /// <summary>
        /// Searches a list of directory ordered by priority for the selected file
        /// </summary>
        /// <param name="filename">The filename to look for</param>
        /// <param name="sourcePaths">paths used for lookup</param>
        /// <returns>The file physical path, or null on no match</returns>
        public static string LookupFile(string filename, Dictionary<int, string> sourcePaths) {
            return Globals.LookupFile(filename, sourcePaths, false);
        }

        /// <summary>
        /// Searches a list of directory ordered by priority for the selected file
        /// </summary>
        /// <param name="filename">The filename to look for</param>
        /// <param name="sourcePaths">paths used for lookup</param>
        /// <param name="virtualMode">Wether to treat source as virtual paths</param> 
        /// <returns>The file physical path when virtualMode is false, a virtual path otherwise.</returns>
        public static string LookupFile(string filename, Dictionary<int, string> sourcePaths, bool virtualMode) {
            if (sourcePaths != null && sourcePaths.Count > 0) {
                foreach (KeyValuePair<int, string> sourceDir in sourcePaths) {
                    string currentPath = sourceDir.Value + "/" + filename;

                    if (!virtualMode) {
                        if (System.IO.File.Exists(currentPath)) {
                            return currentPath;
                        }
                    } else {
                        string physicalPath = Globals.AbsPath(currentPath);
                        if (System.IO.File.Exists(physicalPath)) {
                            return currentPath;
                        }                    
                    }
                }
            }

            return null;
        }
        #endregion

        #region Strings
        public static string UCFirst(string s)
        {
            // Check for empty string.
            if (string.IsNullOrEmpty(s))
            {
                return string.Empty;
            }
            // Return char and concat substring.
            return char.ToUpper(s[0]) + s.Substring(1);
        }
        #endregion

        #region Streams
        public static MemoryStream GetStreamFromString(string s) {
            MemoryStream streamResult = new MemoryStream();
            StreamWriter streamResultWriter = new StreamWriter(streamResult);
            streamResultWriter.Write(s);
            streamResultWriter.Flush();

            streamResult.Position = 0;

            return streamResult;
        }
        #endregion

        #region Page Extension
        public static System.Web.UI.Control FindControlRecursive(System.Web.UI.Control ctrl, string controlID) { 
            if (string.Compare(ctrl.ID, controlID, true) == 0) { 
                // We found the control! 
                return ctrl; 
            } else { 
                // Recurse through ctrl's Controls collections 
                foreach (System.Web.UI.Control child in ctrl.Controls) {
                    System.Web.UI.Control lookFor = FindControlRecursive(child, controlID); 

                    if (lookFor != null) return lookFor; // We found the control 
                } 
                // If we reach here, control was not found 
                return null; 
            }
        }
        #endregion

        #region Reflection methods
        public static Dictionary<string, string> GetClassProperties(System.Type t, string[] allowedTypes)
        {
            PropertyInfo[] props = t.GetProperties(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public);
            Dictionary<string, string> validProps = new Dictionary<string, string>();
            if(props.Length > 0){
                foreach(PropertyInfo p in props){
                    string pType = p.PropertyType.FullName;
                    if (Array.IndexOf(allowedTypes, pType) >= 0)
                    {
                        validProps.Add(p.Name, pType);
                    }
                }
            }

            return validProps;
        }
        #endregion
    }
}
